
#include "type.h"
#include "value_move_config.h"

#define current_value       0
#define target_value        1
#define begin_value         2
#define end_value           4
#define step_value          5
#define circle_move_flag    6

#define OFFSET              7

static volatile uint16_t VALUE_MOVES[VALUE_MOVE_NUM_MAX*OFFSET];

void value_move_init(void)
{
    uint8_t i;
    for (i = 0; i < VALUE_MOVE_NUM_MAX*OFFSET; i++) {
        VALUE_MOVES[i] = 0;
    }
	value_move_hal_init_config(); 
}

void value_move_tick_handler(void)
{
    uint8_t i;
    uint8_t j;
	for (i = 0; i < VALUE_MOVE_NUM_MAX; i++) {
        j = i*OFFSET;
        if(VALUE_MOVES[j+current_value] == VALUE_MOVES[j+target_value]){
            if(VALUE_MOVES[j+circle_move_flag] == 0){
                continue;
            }
            else{
                if(VALUE_MOVES[j+target_value] == VALUE_MOVES[j+begin_value]){
                    VALUE_MOVES[j+target_value] = VALUE_MOVES[j+end_value];
                }
                else{
                    VALUE_MOVES[j+target_value] = VALUE_MOVES[j+begin_value];
                }
            }
        }

        if(VALUE_MOVES[j+current_value] > VALUE_MOVES[j+target_value]){
            if(VALUE_MOVES[j+current_value] - VALUE_MOVES[j+target_value] > VALUE_MOVES[j+step_value]){
                VALUE_MOVES[j+current_value] -= VALUE_MOVES[j+step_value];
            }
            else{
                VALUE_MOVES[j+current_value] = VALUE_MOVES[j+target_value];
            }
            value_move_set_value_event(i, VALUE_MOVES[j+current_value]);
        }
        else if(VALUE_MOVES[j+current_value] < VALUE_MOVES[j+target_value]){
            if(VALUE_MOVES[j+target_value] - VALUE_MOVES[j+current_value] > VALUE_MOVES[j+step_value]){
                VALUE_MOVES[j+current_value] += VALUE_MOVES[j+step_value];
            }
            else{
                VALUE_MOVES[j+current_value] = VALUE_MOVES[j+target_value];
            }
            value_move_set_value_event(i, VALUE_MOVES[j+current_value]);
        }
    }
}

//move_ticks: how many ticks will take to move "current_value" to "target_value"
void value_move_to_value_by_tick(uint8_t value_move_num, uint16_t set_target_value, uint16_t move_ticks)
{
    uint8_t j;
    j = value_move_num*OFFSET;
    if(VALUE_MOVES[j+current_value] == set_target_value){
        return;
    }
    if(move_ticks > 0){
        if(VALUE_MOVES[j+current_value] > set_target_value){
            VALUE_MOVES[j+step_value] = VALUE_MOVES[j+current_value] - set_target_value;
        }
        else if(VALUE_MOVES[j+current_value] < set_target_value){
            VALUE_MOVES[j+step_value] = set_target_value - VALUE_MOVES[j+current_value];
        }
        if(VALUE_MOVES[j+step_value] > move_ticks){
            VALUE_MOVES[j+step_value] = VALUE_MOVES[j+step_value]/move_ticks;
        }
        else{
            VALUE_MOVES[j+step_value] = 1;
        }
    }
    else{
        VALUE_MOVES[j+current_value] = set_target_value;
        value_move_set_value_event(value_move_num, VALUE_MOVES[j+current_value]);
    }
    VALUE_MOVES[j+target_value] = set_target_value;
}

//set_step_value: how many steps pre tick
void value_move_to_value_by_step(uint8_t value_move_num, uint16_t set_target_value, uint16_t set_step_value)
{
    uint8_t j;
    j = value_move_num*OFFSET;
    if(VALUE_MOVES[j+current_value] == set_target_value){
        return;
    }
    if(set_step_value > 0){
        if(VALUE_MOVES[j+current_value] > set_target_value){
            if(set_step_value > (VALUE_MOVES[j+current_value] - set_target_value)){
                set_step_value = VALUE_MOVES[j+current_value] - set_target_value;
            }
        }
        else if(VALUE_MOVES[j+current_value] < set_target_value){
            if(set_step_value > (set_target_value - VALUE_MOVES[j+current_value])){
                set_step_value = set_target_value - VALUE_MOVES[j+current_value];
            }
        }
        VALUE_MOVES[j+step_value] = set_step_value;
    }
    VALUE_MOVES[j+target_value] = set_target_value;
}

//the "current_value" move to the "begin_value" in the first round
//period_ticks: how many ticks will take to move "begin_value" to "end_value"
void value_move_circle_move_by_tick(uint8_t value_move_num, uint16_t set_begin_value, uint16_t set_end_value, uint16_t period_ticks)
{
    uint16_t all_steps;
    uint8_t j;
    if(set_begin_value == set_end_value){
        return;
    }

    if(set_begin_value > set_end_value){
        all_steps = set_begin_value - set_end_value;
       }
    else{
        all_steps = set_end_value - set_begin_value;
    }
    if(all_steps > period_ticks){
        all_steps = all_steps/period_ticks;
    }
    else{
        all_steps = 1;
    }

    if(period_ticks > 0){
        j = value_move_num*OFFSET;
        VALUE_MOVES[j+begin_value] = set_begin_value;
        VALUE_MOVES[j+end_value] = set_end_value;
        VALUE_MOVES[j+step_value] = all_steps;
        VALUE_MOVES[j+circle_move_flag] = 1;
        VALUE_MOVES[j+target_value] = set_begin_value;
    }
}

//the "current_value" move to the "begin_value" in the first round
//set_step_value: how many steps pre tick
void value_move_circle_move_by_step(uint8_t value_move_num, uint16_t set_begin_value, uint16_t set_end_value, uint16_t set_step_value)
{
    uint8_t j;
    if(set_begin_value == set_end_value){
        return;
    }
    if(set_step_value > 0){
        j = value_move_num*OFFSET;
        VALUE_MOVES[j+begin_value] = set_begin_value;
        VALUE_MOVES[j+end_value] = set_end_value;
        VALUE_MOVES[j+step_value] = set_step_value;
        VALUE_MOVES[j+circle_move_flag] = 1;
        VALUE_MOVES[j+target_value] = set_begin_value;
    }
}

void value_move_stop_move(uint8_t value_move_num)
{
    value_move_num = value_move_num*OFFSET;
    VALUE_MOVES[value_move_num+circle_move_flag] = 0;
    VALUE_MOVES[value_move_num+target_value] = VALUE_MOVES[value_move_num+current_value];
}
